Skip to content

Add benchmark to PathFinder and fix search hot spots - #959

Merged
sven-n merged 1 commit into
MUnique:masterfrom
eduardosmaniotto:perf/pathfinding-benchmarks-and-hotspots
Sep 15, 2026
Merged

sven-n merged 1 commit into
MUnique:masterfrom
eduardosmaniotto:perf/pathfinding-benchmarks-and-hotspots

Conversation

@eduardosmaniotto

Copy link
Copy Markdown
Contributor

Summary

No BenchmarkDotNet coverage existed for the A*/Dijkstra PathFinder
(only an ad-hoc Stopwatch test). This PR adds a dedicated benchmark
project and fixes the hot spots it exposed, keeping all public APIs
unchanged.

New: tests/MUnique.OpenMU.Pathfinding.Benchmarks/
(PathFinderBenchmarks.cs: short/diagonal/wall-detour/unreachable on
ScopedGridNetwork, long path on FullGridNetwork, MaximumDistance path).

Changes (src/Pathfinding/)

  • Point.cs: EuclideanDistanceSquaredTo() (int mult, no Math.Pow/Abs); EuclideanDistanceTo() reuses it.
  • PathFinder.cs: cached _maximumDistanceSquared; squared distance checks with early-outs; Elapsed.TotalMilliseconds metrics fix; removed dead Heuristic null checks; GetCalculatedPath() builds + reverses one List.
  • FullGridNetwork.cs: Prepare() for loop instead of _nodes.Where(...) LINQ.
  • ScopedGridNetwork.cs: BitOperations.Log2() instead of Math.Log(x, 2).
  • BinaryMinHeap{T}.cs: loop indices as locals instead of shared _i/_parentIndex/_left/_right fields; renamed helpers to Swap/Compare.

Benchmarks

dotnet run --project tests/MUnique.OpenMU.Pathfinding.Benchmarks -c Release -- --filter '*PathFinderBenchmarks*' --job short --warmupCount 2 --iterationCount 5

Before:

Method Mean Allocated
Scoped_ShortStraightPath 4.074 µs 2.23 KB
Scoped_DiagonalPath 17.482 µs 7.38 KB
Scoped_LongerPathAroundWall 26.891 µs 12.02 KB
Scoped_UnreachableTarget 2.733 µs 1.69 KB
FullGrid_LongerPath 163.510 µs 35.27 KB
Scoped_WithMaximumDistance 38.312 µs 11.98 KB

After:

Method Mean Allocated
Scoped_ShortStraightPath 3.469 µs (-15%) 2.09 KB
Scoped_DiagonalPath 15.851 µs (-9%) 7.24 KB
Scoped_LongerPathAroundWall 27.748 µs (+3%) 11.88 KB
Scoped_UnreachableTarget 2.713 µs (~0%) 1.69 KB
FullGrid_LongerPath 104.088 µs (-36%) 35.23 KB
Scoped_WithMaximumDistance 28.181 µs (-26%) 11.88 KB

Verification

  • dotnet test tests/MUnique.OpenMU.Pathfinding.Tests -c Release: 9/9 passed.
  • No public API changes (INetwork, IPriorityQueue<T>, IPathFinder untouched).

Add tests/MUnique.OpenMU.Pathfinding.Benchmarks with scoped,
full-grid, unreachable and MaximumDistance scenarios.

Optimize hot paths without changing public API:
- Point: add EuclideanDistanceSquaredTo, avoid Math.Pow
- PathFinder: cached MaximumDistanceSquared, fixed Elapsed
  metrics bug (Stopwatch ticks vs TimeSpan ticks), removed dead
  null checks, single-pass path reconstruction
- FullGridNetwork.Prepare: for loop instead of LINQ over 65k nodes
- ScopedGridNetwork.Prepare: BitOperations.Log2 instead of Math.Log
- BinaryMinHeap: method locals instead of shared int fields,
  clearer Swap/Compare helpers
@sven-n
sven-n merged commit a45a9bc into MUnique:master Sep 15, 2026
2 checks passed
@eduardosmaniotto
eduardosmaniotto deleted the perf/pathfinding-benchmarks-and-hotspots branch September 15, 2026 20:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants